package org.javaboy.securitydy.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.javaboy.securitydy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;



/**
 * @Author 江南一点雨
 * @Site www.javaboy.org 2019-08-11 17:16
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
    @Autowired
    MyFilter myFilter;
    @Autowired
    MyAccessDecisionManager myAccessDecisionManager;

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    // 配置支持json登录
    @Bean
    MyAuthenticationFilter myAuthenticationFilter() throws Exception {
        MyAuthenticationFilter filter = new MyAuthenticationFilter();
        filter.setAuthenticationManager(authenticationManagerBean());
        // 登录成功和失败的配置在此处
//        filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() { //登录成功的处理
//            @Override// authentication保存了登录成功后的信息
//            public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp,
//                                                Authentication authentication) throws IOException, ServletException {
//                resp.setContentType("application/json;charset=utf-8");
//                PrintWriter out = resp.getWriter();
//                Map<String, Object> map = new HashMap<>();
//                map.put("status", 200);
//                map.put("msg", authentication.getPrincipal());
//                out.write(new ObjectMapper().writeValueAsString(map));
//                out.flush();
//                out.close();
//            }
//        });
//        filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {//登录失败的处理
//            @Override // e登录失败的异常
//            public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,
//                                                AuthenticationException e) throws IOException, ServletException {
//                resp.setContentType("application/json;charset=utf-8");
//                PrintWriter out = resp.getWriter();
//                Map<String, Object> map = new HashMap<>();
//                map.put("status", 401);
//                if (e instanceof LockedException) {
//                    map.put("msg", "账户被锁定，登录失败!");
//                } else if (e instanceof BadCredentialsException) {
//                    map.put("msg", "用户名或密码输入错误，登录失败!");
//                } else if (e instanceof DisabledException) {
//                    map.put("msg", "账户被禁用，登录失败!");
//                } else if (e instanceof AccountExpiredException) {
//                    map.put("msg", "账户过期，登录失败!");
//                } else if (e instanceof CredentialsExpiredException) {
//                    map.put("msg", "密码过期，登录失败!");
//                } else {
//                    map.put("msg", "登录失败!");
//                }
//                out.write(new ObjectMapper().writeValueAsString(map));
//                out.flush();
//                out.close();
//            }
//        });
        return filter;
    }

    //    @Bean
//    RoleHierarchy roleHierarchy() {
//        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
//        String hierarchy = "dba > admin \n admin > user";
//        roleHierarchy.setHierarchy(hierarchy);
//        return roleHierarchy;
//    }
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        return super.userDetailsService();
    }

    /**
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O o) {
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        o.setSecurityMetadataSource(myFilter);
                        return o;
                    }
                })
                .and()
                .formLogin()
                .permitAll()
                .and()
                .csrf().disable();
        // 配置json登录
        http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
}


//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//
//        http.authorizeRequests()//开启配置
//                .antMatchers("/admin/**").hasRole("admin")//路径符合这个需要admin角色
////                .antMatchers("user/**").hasAnyRole("admin", "user")//路径符合这个，需要这两个的任意一个
//                .antMatchers("/user/**").access("hasAnyRole('user','admin')")
//                .anyRequest().authenticated()//其他请求，登录后就可以访问
//                .and()
//                .formLogin()//表单登录
//                .loginProcessingUrl("/doLogin")//处理登录请求的地址
//                .loginPage("/login")//配置登录页面（实际上还是一个请求地址） 前后端分类不存在这种页面 这里还是访问的应该请求，会根据这请求去返回登录页面
//                .usernameParameter("uname")//修改登录的key
//                .passwordParameter("passwd")//修改登录的key
//                .successHandler(new AuthenticationSuccessHandler() { //登录成功的处理
//                    @Override// authentication保存了登录成功后的信息
//                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp,
//                                                        Authentication authentication) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 200);
//                        map.put("msg", authentication.getPrincipal());
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .failureHandler(new AuthenticationFailureHandler() {//登录失败的处理
//                    @Override // e登录失败的异常
//                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,
//                                                        AuthenticationException e) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 401);
//                        if (e instanceof LockedException) {
//                            map.put("msg", "账户被锁定，登录失败!");
//                        } else if (e instanceof BadCredentialsException) {
//                            map.put("msg", "用户名或密码输入错误，登录失败!");
//                        } else if (e instanceof DisabledException) {
//                            map.put("msg", "账户被禁用，登录失败!");
//                        } else if (e instanceof AccountExpiredException) {
//                            map.put("msg", "账户过期，登录失败!");
//                        } else if (e instanceof CredentialsExpiredException) {
//                            map.put("msg", "密码过期，登录失败!");
//                        } else {
//                            map.put("msg", "登录失败!");
//                        }
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .permitAll()
//                .and()
//                .logout()
//                .logoutUrl("/logout") //配置注销请求的地址
//                .logoutSuccessHandler(new LogoutSuccessHandler() {//注销成功后的回调
//                    @Override
//                    public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp,
//                                                Authentication authentication) throws IOException, ServletException {
//                        resp.setContentType("application/json;charset=utf-8");
//                        PrintWriter out = resp.getWriter();
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("status", 200);
//                        map.put("msg", "注销登录成功!");
//                        out.write(new ObjectMapper().writeValueAsString(map));
//                        out.flush();
//                        out.close();
//                    }
//                })
//                .and()
//                .csrf().disable();
//
//        /**
//         * 权限不足处理
//         */
//        http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {
//            @Override
//            public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {
//
//                httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//
//                Map<String, Object> failureMap = new HashMap<>();
//                failureMap.put("code", 403);
//                failureMap.put("msg", "权限不足！");
//
//                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
//            }
//        });
//        /**
//         * 未登陆处理
//         */
//        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
//            @Override
//            public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
//
//
//                httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//
//                Map<String, Object> failureMap = new HashMap<>();
//                failureMap.put("code", 401);
//                failureMap.put("msg", "请先登录！");
//
//                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
//            }
//        });

